<template>
	<div class="g-upload-select-modal">
		<!-- 选择文件 -->
		<a-modal
			:centered="true"
			width="600px"
			:body-style="{ padding: '40px' }"
			title="批量上传"
			:open="props.visible"
			:footer="null"
			@cancel="emit('update:visible', false)"
		>
			<div class="g-upload-select-modal-info">
				<div>
					<div class="title-area">
						<div>
							<i class="iconfont icon-information-fill"></i>
						</div>
						<h6>
							<slot name="title">{{ title }}</slot>
						</h6>
					</div>
					<p>
						<slot name="subTitle">{{ subTitle }}</slot>
					</p>
				</div>
			</div>
			<div class="g-upload-select-modal-content">
				<div class="g-upload-select-modal-title">选择上传方式</div>
				<div class="g-upload-select-modal-btns">
					<a-form-item-rest>
						<a-upload multiple :show-upload-list="false" :file-list="fileList" :custom-request="customRequest" @change="onFolderChange">
							<a-button type="default" class="icon-button" @click="onSelectFiles">
								<PictureOutlined />
								图片
							</a-button>
						</a-upload>
					</a-form-item-rest>
					<a-form-item-rest>
						<a-upload directory :show-upload-list="false" :file-list="fileList" :custom-request="customRequest" @change="onFolderChange">
							<a-button type="default" class="icon-button" @click="onSelectFolder">
								<FolderOutlined />
								文件夹
							</a-button>
						</a-upload>
					</a-form-item-rest>
				</div>
			</div>
		</a-modal>

		<!-- 上传中 --><!-- 上传完成 -->
		<a-modal v-model:open="uploadingVisible" :centered="true" width="600px" title="批量上传" :footer="null" @cancel="onUploadingCancel">
			<div class="g-upload-loading-content">
				<i v-if="isFinish" class="iconfont icon-checkbox-circle-fill"></i>
				<GLoading v-else :spinning="true" />
				<div v-if="isCancel" class="g-upload-loading-title">{{ isFinish ? '上传完成' : '上传中...' }}</div>
				<!-- 入库数量 -->
				<ul class="g-upload-loading-info">
					<li>
						<span>入库成功数量：</span>
						<span>{{ successNum || 0 }}</span>
					</li>
					<li>
						<span>入库失败数量：</span>
						<span class="underline" @click="handleOpenUploadRecord">{{ errorList.length || 0 }}</span>
					</li>
				</ul>
				<a-button v-if="isFinish" type="primary" style="margin-top: 24px" @click="onUploadingCancel">确定</a-button>
			</div>
		</a-modal>

		<!-- 上传记录 -->
		<a-modal
			v-model:open="uploadRecordVisible"
			:centered="true"
			wrap-class-name="upload-record-modal"
			width="600px"
			title="上传结果"
			:footer="null"
			:body-style="{ padding: '40px 32px' }"
		>
			<div class="g-upload-record-content">
				<!-- <ul class="g-upload-record-list">
					<li :key="item.name" v-for="(item, index) in errorList">
						<span>{{ index + 1 }}</span>
						<span :title="item.name">{{ item.name }}</span>
						<span :title="item.error">{{ item.error }}</span>
					</li>
				</ul> -->
				<a-table :pagination="false" :data-source="errorList" :columns="uploadRecordColumns" />
			</div>
		</a-modal>
	</div>
</template>

<script setup lang="ts">
import { isDpi } from '@/global-utils/check';
import { UploadChangeParam, UploadFile, message } from 'ant-design-vue';
import GLoading from '@/global-components/GlobalLoading/GlobalLoading.vue';
import { confirm } from '@/global-utils/antd.util';
import { BoxManageApi } from '@/view-modules/config-manage/api';

interface UploadSeleceModalProps {
	visible?: boolean;
	title?: string;
	subTitle?: string;
	accept?: string;
	boxSerial?: string | null;
	dpi?: [number, number] | [[number, number], [number, number]];
	maxFileSize?: number;
	type?: number | null;
	fileName?: boolean;
	// eslint-disable-next-line no-use-before-define
	moduleType?: ModuleType;
	beforeUpload?: (file: File) => Promise<boolean | string>;
	onSuccess?: (res: any) => Promise<any>;
}
const props = withDefaults(defineProps<UploadSeleceModalProps>(), {
	visible: false,
	title: '上传照片',
	subTitle: '图片格式JPG、PNG',
	maxFileSize: -1,
	accept: 'png,jpg',
	dpi: undefined,
	type: null,
	fileName: true,
	boxSerial: null,
	// eslint-disable-next-line no-use-before-define
	moduleType: ModuleType.AI_UNIFORM,
	beforeUpload: () => Promise.resolve(true),
	onSuccess: () => Promise.resolve()
});

const emit = defineEmits(['update:visible', 'on-cancel']);

const $message: any = inject('$message');

enum ModuleType {
	SYSTEM = 0, // 系统Logo
	SYSTEM_SOFTWARE_UPGRADE = 1, // 系统软件升级
	SYSTEM_HARDWARE_UPGRADE = 2, // 系统硬件升级
	AI_UNIFORM = 3, // AI工服库接口
	AI_FACE = 4, // AI人脸接口
	AI_SDK = 7 // AI服务接口
}
let isFlag = false;
// 选择文件
const onSelectFiles = (): void => {
	isFlag = false;
	emit('update:visible', false);
};
// 选择文件夹
const onSelectFolder = (): void => {
	isFlag = false;
	emit('update:visible', false);
};

// 上传文件夹
const successNum = ref(0);
const errorList = ref<any[]>([]);
const uploadingVisible = ref(false);
// 特殊标识
const special = ref(false);
// 是否完成
const fileList = ref<UploadFile[]>([]);
const isFinish = computed(() => {
	return special.value || successNum.value + errorList.value.length === fileList.value.length;
});
// 是否中断上传
let isCancel = false;
const onFolderChange = (info: UploadChangeParam<UploadFile<any>>): void => {
	fileList.value = info.fileList;

	// console.log('fileList:', fileList.value);
};

// 上传验证和接口调用
const customRequest = async (): Promise<void> => {
	// console.log('=========');

	if (isFlag) {
		return;
	}
	isFlag = true;
	if (!uploadingVisible.value) {
		uploadingVisible.value = true;
	}
	for (let index = 0; index < fileList.value.length; index++) {
		if (fileList.value.length > 100) {
			isCancel = true;

			$message.error('文件个数超出');
			uploadingVisible.value = false;
			emit('update:visible', true);
			fileList.value = [];
		}
		if (isCancel) {
			break;
		}
		try {
			const file = fileList.value[index].originFileObj as any;

			// 验证文件大小
			if (props.maxFileSize !== -1) {
				const maxSize = props.maxFileSize * 1024 * 1024;
				if (file.size > maxSize) {
					throw {
						type: 'verify',
						error: '超出文件大小',
						name: file.name
					};
				}
			}

			// 验证文件类型
			if (props.accept.trim() !== '') {
				const postfix: string = file?.name?.split('.')?.slice(-1)[0];
				if (!props?.accept?.split(',')?.includes(postfix)) {
					throw {
						type: 'verify',
						error: '文件类型错误',
						name: file.name
					};
				}
			}

			// 验证分辨率
			if (props.dpi) {
				try {
					await isDpi(file, props?.dpi);
				} catch (error) {
					throw {
						type: 'verify',
						error: '分辨率错误',
						name: file.name
					};
				}
			}

			if (props.beforeUpload) {
				try {
					await props.beforeUpload(file);
				} catch (error) {
					throw {
						type: 'verify',
						error: error,
						name: file.name
					};
				}
			}

			const formData = new FormData();
			formData.append('files', file);
			const param = {
				boxSerial: props.boxSerial,
				batchMark: 1
			};
			formData.append('batchMark', JSON.stringify(param.batchMark));
			formData.append('boxSerial', props.boxSerial);
			formData.append('type', props.type);
			// console.log('formData:', formData);

			try {
				const res: TsRes = await BoxManageApi.faceRecognitionImgUpload(formData);
				await props.onSuccess({ ...res.data, name: file.name });
				successNum.value++;
			} catch (error: any) {
				throw {
					type: 'fail',
					error: error?.data?.message || '上传失败',
					code: error?.data?.code || 0,
					name: file.name
				};
			}
		} catch (error: any) {
			// console.log('error:', error);

			if (error?.type === 'fail') {
				if (error?.code === -14 || error?.code === 15) {
					isCancel = true;
					special.value = true;
					message.error(error.error);
				} else {
					errorList.value.push({ name: error.name, error: error.error });
				}
			} else if (error?.type === 'verify') {
				errorList.value.push({ name: error.name, error: error.error });
			} else {
				errorList.value.push({ name: '未知文件名', error: '上传失败' });
			}
		}
	}
};

// 上传结果
const uploadRecordColumns: TsGlobalType.TsTableColumn[] = [
	{ dataIndex: 'name', title: '文件名称', width: 240, ellipsis: true },
	{ dataIndex: 'error', title: '失败原因', width: 240, ellipsis: true }
];
/**
 * 取消上传
 */
const run = (): void => {
	special.value = false;
	isCancel = false;
	uploadingVisible.value = false;
	successNum.value = 0;
	errorList.value = [];
	fileList.value = [];
	emit('on-cancel');
};
const onUploadingCancel = (): void => {
	uploadingVisible.value = true;
	if (!isFinish.value) {
		confirm({
			title: '文件上传中，是否中断上传并退出',
			onOk: () => {
				isCancel = true;
				run();
			}
		});
		return;
	}
	run();
};

/**
 * 上传记录
 */
const uploadRecordVisible = ref<boolean>(false);
const handleOpenUploadRecord = (): void => {
	if (errorList.value.length === 0) {
		return;
	}
	uploadRecordVisible.value = true;
};
</script>

<style lang="less" scoped>
.g-upload-select-modal-info {
	display: flex;
	gap: 0 10px;

	.title-area {
		display: flex;
	}

	i {
		color: @link01;
	}

	h6 {
		margin: 0;
		padding-top: 3px;
		font-size: 12px;
		color: @text02;
	}

	p {
		margin-top: 8px;
		font-size: 12px;
		line-height: 20px;
		color: @text01;
	}
}

.g-upload-select-modal-content {
	display: flex;
	align-items: center;
	margin-top: 40px;
	gap: 0 24px;
	font-size: 14px;
	color: @text02;

	.g-upload-select-modal-btns {
		display: flex;
		gap: 0 8px;
	}
}

.g-upload-loading-content {
	display: flex;
	flex-direction: column;
	align-items: center;
	padding: 50px 0;

	.g-upload-loading-title {
		margin: 20px 0;
		font-size: 14px;
		font-weight: 700;
		color: @text01;
	}

	.g-upload-loading-info {
		font-size: 14px;
		color: @text01;

		.underline {
			text-decoration: underline;
			color: @link01;
			cursor: pointer;
		}

		> li {
			margin-top: 16px;
		}
	}

	.icon-checkbox-circle-fill {
		height: 50px;
		font-size: 64px;
		color: @success01;
		transform: translateY(-30px);
	}
}

.upload-record-modal {
	.g-upload-record-content {
		overflow: scroll;
		height: 266px;
		margin-bottom: 32px;
		border: 1px solid @borderColor02;
		border-radius: 6px;

		.g-upload-record-title {
			font-size: 14px;
			font-weight: 700;
			color: @text01;
		}

		.g-upload-record-list {
			overflow: auto;
			max-height: 600px;
			margin-top: 16px;
			border: 1px solid @borderColor01;
			border-radius: 2px;

			li {
				display: flex;
				height: 38px;
				border-bottom: 1px solid @borderColor01;
				font-size: 14px;
				color: @text01;
				align-items: center;

				&:last-child {
					border-bottom: none;
				}

				> span {
					display: block;

					&:nth-child(1) {
						width: 83px;
						padding-left: 24px;
					}

					&:nth-child(2),
					&:nth-child(3) {
						overflow: hidden;
						padding-right: 24px;
						text-align: center;
						white-space: nowrap;
						text-overflow: ellipsis;
						flex: 1;
					}
				}
			}
		}
	}
}
</style>
